#define  _CRT_SECURE_NO_WARNINGS 1
//#include "head.h"


//顺序读写函数
// 函数名    功能            适用于
// fgetc()   字符输入(读)函数    所有输入流  --> 文件流(pf)/stdin
// fputc()   字符输出(写)函数    所有输出流  --> 文件流(pf)/stdout
// 
// fgets()   文本行输入函数    所有输入流
// fputs()   文本行输出函数    所有输出流
// 
// fscanf()   格式化输入函数    所有输入流
// fprintf()  格式化输出函数    所有输出流
// 
// fread()   二进制输入函数    文件输入流
// fwrite()  二进制输出函数    文件输出流
// 

//对比：
// scanf(输入->键盘) / printf(输出->屏幕)    针对标准输入(stdin-键盘)输出(stdout-屏幕)的格式化输入输出函数
// fscanf()/fprintf()    针对所有输入流/输出流的格式化输入/输出函数
// 
// 
// sscanf()
// int sscanf(const char* str, const char* format, ...);
// 从字符串中读格式化的数据, 返回读取的字符个数 （从字符串中还原出格式化数据）
// 
// sprintf()
// int sprintf(char* str, const char* format, ...);
// 写格式化的数据到字符串中, 返回写入的字符个数  （把格式化的数据转换(存放)成字符串）
// 



// 写字符到文件（覆盖原本内容）
//int fputc(int ch, FILE* stream);
//int main()
//{
//	//打开文件
//	FILE* pf = fopen("data.txt", "w");
//	if (pf == NULL)
//	{
//		perror("open file error\n");
//		return -1;
//	}
//
//	//写文件
//    //fputc('a', pf);
//
//	for (char i = 'a'; i <= 'z'; i++)
//	{
//		fputc(i, pf);
//		//fputc(' ', pf);
//	}
//
//	//关闭文件
//    fclose(pf);
//	pf = NULL;
//
//	return 0;
//}


//从文件中读字符
//int fgetc(FILE* stream);
//int main()
//{
//	//打开文件
//	FILE* pf = fopen("data.txt", "r"); //指向文件起始位置
//	if (pf == NULL)
//	{
//		perror("fopen");
//        return -1;
//	}
//
//	//读文件
//	//int ch = fgetc(pf);
//	//printf("%c", ch); //a
//
//	//ch = fgetc(pf);
//	//printf("%c", ch); //b
//
//	//ch = fgetc(pf);
//	//printf("%c", ch); //c
//	//每次读完之后，指针会自动后移
//
//	int ch = 0;
//	//读取成功 返回字符的ASCII码值
//	while ((ch = fgetc(pf)) != EOF) //读取失败（设置错误状态值 ferror）、文件末尾返回 EOF
//	{
//		printf("%c ", ch); 
//	}
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//
//	return 0;
//}


// 写文本行到文件（覆盖原本内容）
//int fputs(const char* s, FILE* stream);
//int main()
//{
//	//打开文件
//	FILE* pf = fopen("data.txt", "w");
//	if (pf == NULL)
//	{
//        perror("open file error\n");
//        return -1;
//	}
//
//	//写文件
//	fputs("hello world\n", pf); //需要手动换行
//    fputs("hello c\n", pf);
//
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//
//	return 0;
//}


// 从文件中读文本行
//char* fgets(char* str, int num, FILE* stream);
//int main()
//{
//	//打开文件
//    FILE* pf = fopen("data.txt", "r");
//    if (pf == NULL)
//    {
//        perror("open file error\n");
//        return -1;
//    }
//
//    //读文件
//    char arr[8];
//    fgets(arr, 8, pf); // 最后一个字符给'\0'
//    printf("%s", arr);
//
//    char arr2[20];
//    fgets(arr2, 20, pf); // 读到'\n'时停止，在'\n'后添加'\0'
//    printf("%s", arr2);
//
//    //关闭文件
//    fclose(pf);
//    pf = NULL;
//
//    return 0;
//}


//向文件写入数据(覆盖掉原本内容)
//int fprintf(FILE* stream, const char* format, ...);
//int main()
//{
//	//打开文件
//    FILE* pf = fopen("data.txt", "w");
//    if (pf == NULL)
//    {
//        perror("open file error\n");
//        return -1;
//    }
//
//    //写文件
//    char name[] = "zhangsan";
//    int age = 18;
//    double score = 90.9;
//
//    printf("name = %s\nage = %d\nscore = %lf\n", name, age, score);
//    fprintf(pf, "name = %s\nage = %d\nscore = %lf\n", name, age, score);
//    //多一个参数
//
//    //关闭文件
//    fclose(pf);
//    pf = NULL;
//
//	return 0;
//}


//从文件中读数据
//int fscanf(FILE* stream, const char* format, ...);
//struct S
//{
//    char name[32];
//    int age;
//    double score;
//};
//
//int main()
//{
//	//打开文件
//    FILE* pf = fopen("data.txt", "r");
//    if (pf == NULL)
//    {
//        perror("open file error\n");
//        return -1;
//    }
//
//    //读文件
//    struct S s = { 0 };
//    fscanf(pf, "%s %d %lf", s.name, &(s.age), &(s.score));
//    printf("name = %s\nage = %d\nscore = %lf\n", s.name, s.age, s.score);
//
//
//    //也可以从键盘读数据(标准输入流stdin) --> 等价于 scanf
//    //fscanf(stdin, "%s %d %lf", s.name, &(s.age), &(s.score));
//
//
//    //关闭文件
//    fclose(pf);
//    pf = NULL;
//
//	return 0;
//}


// 二进制写函数
//size_t fwrite(const void* ptr, size_t size, size_t count, FILE* stream)
//{
//    //ptr: 要写入的数据
//    //size: 每个数据的大小
//    //count: 要写入的数据个数
//    //stream: 文件指针
//    //返回值: 成功写入的数据个数
//    //失败: 0
//    return fwrite(ptr, size, count, stream);
//}

//struct S
//{
//    char name[32];
//    int age;
//    double score;
//};
//
//int main()
//{
//    struct S s = { "zhangsan", 18, 90.9 };
//    FILE* pf = fopen("test.txt", "wb");
//    if (pf == NULL)
//    {
//        perror("open file error\n");
//        return -1;
//    }
//
//    //写文件
//    fwrite(&s, sizeof(struct S), 1, pf);
//
//    //关闭文件
//    fclose(pf);
//    pf = NULL;
//
//    return 0;
//}


//二进制读函数
//size_t fread(void* ptr, size_t size, size_t count, FILE* stream)
//{
//    //ptr: 存储读取数据的指针
//    //size: 每个数据大小
//    //count: 要读取的数据个数
//    //stream: 文件指针
//    //返回值: 成功读取的数据个数
//    //失败: 0
//    return fread(ptr, size, count, stream);
//}

//struct S
//{
//    char name[32];
//    int age;
//    double score;
//};
//
//int main()
//{
//    struct S s = { 0 };
//    FILE* pf = fopen("test.txt", "rb");
//    if (pf == NULL)
//    {
//        perror("open file error\n");
//        return -1;
//    }
//
//    //读文件
//    fread(&s, sizeof(struct S), 1, pf);
//    printf("name = %s\nage = %d\nscore = %lf\n", s.name, s.age, s.score);
//
//    //关闭文件
//    fclose(pf);
//    pf = NULL;
//
//    return 0;
//}


//sprintf()
//int sprintf(char* str, const char* format, ...);
//sscanf()
//int sscanf(const char* str, const char* format, ...);
//struct S
//{
//    char name[32];
//    int age;
//    double score;
//};
//
//int main()
//{
//    struct S s = { "zhangsan", 18, 90.9 };
//    char buf[128] = { 0 };
//    sprintf(buf, "%s %d %lf", s.name, s.age, s.score);
//    printf("%s\n", buf); //按照字符串打印
//
//    struct S s2 = { 0 };
//    sscanf(buf, "%s %d %lf", s2.name, &(s2.age), &(s2.score));
//    printf("name = %s\nage = %d\nscore = %lf\n", s2.name, s2.age, s2.score); //按照结构体打印
//
//    return 0;
//}




//文件读取结束的判定：
//feof()
//int feof(FILE* stream);
//返回真，表示文件正常读取到了结束标志而结束。

//ferror()
//int ferror(FILE* stream);
//返回真，表示文件读取时发生错误而结束。

/*
牢记:在文件读取过程中，不能用feof函数的返回值直接用来判断文件的是否结束。
而是应用于当文件读取结束的时候，判断是读取失败结束，还是遇到文件尾结束。
1.文本文件读取是否结束，判断返回值是否为E0F(fgetc)，或者NULL(fgets ) ---> 看参考网站，具体的判断方法。
例如:
	fgetc 判断是否为 EOF
	fgets 判断返回值是否为 NULL。
2.二进制文件的读取结束判断，判断返回值是否小于实际要读的个数。
例如:
	fread 判断返回值是否小于实际要读的个数。
*/


//文件缓冲区
//fflush()
//int fflush(FILE* stream);
//刷新缓冲区，将缓冲区中的数据写入文件。
//fclose()
//int fclose(FILE* stream);
//关闭文件，将缓冲区中的数据写入文件(也会刷新缓冲区)，并释放文件指针。